// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the DSUTIL_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see 
// DSUTIL_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef DSUTIL_EXPORTS
#define DSUTIL_API __declspec(dllexport)
#else
#define DSUTIL_API __declspec(dllimport)
#pragma comment(lib, "dsutil")
#endif

#include "NullRenderers.h"
#include "HdmvClipInfo.h"
#include "H264Nalu.h"
//#include "MediaTypes.h"
#include "MediaTypeEx.h"
#include "vd.h"
#include "text.h"

DSUTIL_API void DumpStreamConfig(TCHAR* fn, IAMStreamConfig* pAMVSCCap);
DSUTIL_API int CountPins(IBaseFilter* pBF, int& nIn, int& nOut, int& nInC, int& nOutC);
DSUTIL_API bool IsSplitter(IBaseFilter* pBF, bool fCountConnectedOnly = false);
DSUTIL_API bool IsMultiplexer(IBaseFilter* pBF, bool fCountConnectedOnly = false);
DSUTIL_API bool IsStreamStart(IBaseFilter* pBF);
DSUTIL_API bool IsStreamEnd(IBaseFilter* pBF);
DSUTIL_API bool IsVideoRenderer(IBaseFilter* pBF);
DSUTIL_API bool IsAudioWaveRenderer(IBaseFilter* pBF);
DSUTIL_API IBaseFilter* GetUpStreamFilter(IBaseFilter* pBF, IPin* pInputPin = NULL);
DSUTIL_API IPin* GetUpStreamPin(IBaseFilter* pBF, IPin* pInputPin = NULL);
DSUTIL_API IPin* GetFirstPin(IBaseFilter* pBF, PIN_DIRECTION dir = PINDIR_INPUT);
DSUTIL_API IPin* GetFirstDisconnectedPin(IBaseFilter* pBF, PIN_DIRECTION dir);
DSUTIL_API void NukeDownstream(IBaseFilter* pBF, IFilterGraph* pFG);
DSUTIL_API void NukeDownstream(IPin* pPin, IFilterGraph* pFG);
DSUTIL_API IBaseFilter* FindFilter(LPCWSTR clsid, IFilterGraph* pFG);
DSUTIL_API IBaseFilter* FindFilter(const CLSID& clsid, IFilterGraph* pFG);
DSUTIL_API CStringW GetFilterName(IBaseFilter* pBF);
DSUTIL_API CStringW GetPinName(IPin* pPin);
DSUTIL_API IFilterGraph* GetGraphFromFilter(IBaseFilter* pBF);
DSUTIL_API IBaseFilter* GetFilterFromPin(IPin* pPin);
DSUTIL_API IPin* AppendFilter(IPin* pPin, LPCTSTR DisplayName, IGraphBuilder* pGB);
DSUTIL_API IPin* InsertFilter(IPin* pPin, LPCTSTR DisplayName, IGraphBuilder* pGB);
DSUTIL_API void ExtractMediaTypes(IPin* pPin, CAtlArray<GUID>& types);
DSUTIL_API void ExtractMediaTypes(IPin* pPin, CAtlList<CMediaType>& mts);
DSUTIL_API void ShowPPage(LPCTSTR DisplayName, HWND hParentWnd);
DSUTIL_API void ShowPPage(IUnknown* pUnknown, HWND hParentWnd);
DSUTIL_API CLSID GetCLSID(IBaseFilter* pBF);
DSUTIL_API CLSID GetCLSID(IPin* pPin);
DSUTIL_API bool IsCLSIDRegistered(LPCTSTR clsid);
DSUTIL_API bool IsCLSIDRegistered(const CLSID& clsid);
DSUTIL_API void CStringToBin(LPCTSTR, CAtlArray<BYTE>&);
DSUTIL_API CString BinToCString(BYTE* ptr, int len);
typedef enum {CDROM_NotFound, CDROM_Audio, CDROM_VideoCD, CDROM_DVDVideo, CDROM_Unknown} cdrom_t;
DSUTIL_API cdrom_t GetCDROMType(TCHAR drive, CAtlList<CString>& files);
DSUTIL_API CString GetDriveLabel(TCHAR drive);
DSUTIL_API bool GetKeyFrames(LPCTSTR fn, CAtlArray<UINT>& kfs);
DSUTIL_API DVD_HMSF_TIMECODE RT2HMSF(REFERENCE_TIME rt, double fps = 0);
DSUTIL_API REFERENCE_TIME HMSF2RT(DVD_HMSF_TIMECODE hmsf, double fps = 0);
DSUTIL_API void memsetd(void* dst, unsigned int c, int nbytes);
DSUTIL_API bool ExtractBIH(const AM_MEDIA_TYPE* pmt, BITMAPINFOHEADER* bih);
DSUTIL_API bool ExtractBIH(IMediaSample* pMS, BITMAPINFOHEADER* bih);
DSUTIL_API bool ExtractAvgTimePerFrame(const AM_MEDIA_TYPE* pmt, REFERENCE_TIME& rtAvgTimePerFrame);
DSUTIL_API bool ExtractDim(const AM_MEDIA_TYPE* pmt, int& w, int& h, int& arx, int& ary);
DSUTIL_API bool MakeMPEG2MediaType(CMediaType& mt, BYTE* seqhdr, DWORD len, int w, int h);
DSUTIL_API unsigned __int64 GetFileVersion(LPCTSTR fn);
DSUTIL_API bool CreateFilter(LPCWSTR DisplayName, IBaseFilter** ppBF, CStringW& FriendlyName);
DSUTIL_API IBaseFilter* AppendFilter(IPin* pPin, IMoniker* pMoniker, IGraphBuilder* pGB);
DSUTIL_API CStringW GetFriendlyName(CStringW DisplayName);
DSUTIL_API HRESULT LoadExternalObject(LPCTSTR path, REFCLSID clsid, REFIID iid, void** ppv);
DSUTIL_API HRESULT LoadExternalFilter(LPCTSTR path, REFCLSID clsid, IBaseFilter** ppBF);
DSUTIL_API HRESULT LoadExternalPropertyPage(IPersist* pP, REFCLSID clsid, IPropertyPage** ppPP);
DSUTIL_API void UnloadExternalObjects();
DSUTIL_API CString MakeFullPath(LPCTSTR path, HINSTANCE hInst = NULL);
DSUTIL_API CString GetMediaTypeName(const GUID& guid);
DSUTIL_API GUID GUIDFromCString(LPCTSTR str);
DSUTIL_API HRESULT GUIDFromCString(LPCTSTR str, GUID& guid);
DSUTIL_API CString CStringFromGUID(const GUID& guid);
DSUTIL_API CStringW UTF8To16(LPCSTR utf8);
DSUTIL_API CStringA UTF16To8(LPCWSTR utf16);
DSUTIL_API CString ISO6391ToLanguage(LPCSTR code);
DSUTIL_API CString ISO6392ToLanguage(LPCSTR code);
DSUTIL_API LCID    ISO6392ToLcid(LPCSTR code);
DSUTIL_API CString ISO6391To6392(LPCSTR code);
DSUTIL_API CString ISO6392To6391(LPCSTR code);
DSUTIL_API CString LanguageToISO6392(LPCTSTR lang);
DSUTIL_API int MakeAACInitData(BYTE* pData, int profile, int freq, int channels);
DSUTIL_API bool DeleteRegKey(LPCTSTR pszKey, LPCTSTR pszSubkey);
DSUTIL_API bool SetRegKeyValue(LPCTSTR pszKey, LPCTSTR pszSubkey, LPCTSTR pszValueName, LPCTSTR pszValue);
DSUTIL_API bool SetRegKeyValue(LPCTSTR pszKey, LPCTSTR pszSubkey, LPCTSTR pszValue);
DSUTIL_API void RegisterSourceFilter(const CLSID& clsid, const GUID& subtype2, LPCTSTR chkbytes, LPCTSTR ext = NULL, ...);
DSUTIL_API void RegisterSourceFilter(const CLSID& clsid, const GUID& subtype2, const CAtlList<CString>& chkbytes, LPCTSTR ext = NULL, ...);
DSUTIL_API void UnRegisterSourceFilter(const GUID& subtype);
DSUTIL_API LPCTSTR GetDXVAMode(const GUID* guidDecoder);
DSUTIL_API void DumpBuffer(const BYTE* pBuffer, int nSize);

class CPinInfo : public PIN_INFO
{
public:
	CPinInfo() {pFilter = NULL;}
	~CPinInfo() {if(pFilter) pFilter->Release();}
};

class CFilterInfo : public FILTER_INFO
{
public:
	CFilterInfo() {pGraph = NULL;}
	~CFilterInfo() {if(pGraph) pGraph->Release();}
};

#define BeginEnumFilters(pFilterGraph, pEnumFilters, pBaseFilter) \
{CComPtr<IEnumFilters> pEnumFilters; \
	if(pFilterGraph && SUCCEEDED(pFilterGraph->EnumFilters(&pEnumFilters))) \
{ \
	for(CComPtr<IBaseFilter> pBaseFilter; S_OK == pEnumFilters->Next(1, &pBaseFilter, 0); pBaseFilter = NULL) \
{ \

#define EndEnumFilters }}}

#define BeginEnumCachedFilters(pGraphConfig, pEnumFilters, pBaseFilter) \
{CComPtr<IEnumFilters> pEnumFilters; \
	if(pGraphConfig && SUCCEEDED(pGraphConfig->EnumCacheFilter(&pEnumFilters))) \
{ \
	for(CComPtr<IBaseFilter> pBaseFilter; S_OK == pEnumFilters->Next(1, &pBaseFilter, 0); pBaseFilter = NULL) \
{ \

#define EndEnumCachedFilters }}}

#define BeginEnumPins(pBaseFilter, pEnumPins, pPin) \
{CComPtr<IEnumPins> pEnumPins; \
	if(pBaseFilter && SUCCEEDED(pBaseFilter->EnumPins(&pEnumPins))) \
{ \
	for(CComPtr<IPin> pPin; S_OK == pEnumPins->Next(1, &pPin, 0); pPin = NULL) \
{ \

#define EndEnumPins }}}

#define BeginEnumMediaTypes(pPin, pEnumMediaTypes, pMediaType) \
{CComPtr<IEnumMediaTypes> pEnumMediaTypes; \
	if(pPin && SUCCEEDED(pPin->EnumMediaTypes(&pEnumMediaTypes))) \
{ \
	AM_MEDIA_TYPE* pMediaType = NULL; \
	for(; S_OK == pEnumMediaTypes->Next(1, &pMediaType, NULL); DeleteMediaType(pMediaType), pMediaType = NULL) \
{ \

#define EndEnumMediaTypes(pMediaType) } if(pMediaType) DeleteMediaType(pMediaType); }}

#define BeginEnumSysDev(clsid, pMoniker) \
{CComPtr<ICreateDevEnum> pDevEnum4$##clsid; \
	pDevEnum4$##clsid.CoCreateInstance(CLSID_SystemDeviceEnum); \
	CComPtr<IEnumMoniker> pClassEnum4$##clsid; \
	if(SUCCEEDED(pDevEnum4$##clsid->CreateClassEnumerator(clsid, &pClassEnum4$##clsid, 0)) \
	&& pClassEnum4$##clsid) \
{ \
	for(CComPtr<IMoniker> pMoniker; pClassEnum4$##clsid->Next(1, &pMoniker, 0) == S_OK; pMoniker = NULL) \
{ \

#define EndEnumSysDev }}}

#define QI(i) (riid == __uuidof(i)) ? GetInterface((i*)this, ppv) :
#define QI2(i) (riid == IID_##i) ? GetInterface((i*)this, ppv) :

template <typename T> __inline void INITDDSTRUCT(T& dd)
{
	ZeroMemory(&dd, sizeof(dd));
	dd.dwSize = sizeof(dd);
}

#define countof(array) (sizeof(array)/sizeof(array[0]))

template <class T>
static CUnknown* WINAPI CreateInstance(LPUNKNOWN lpunk, HRESULT* phr)
{
	*phr = S_OK;
	CUnknown* punk = new T(lpunk, phr);
	if(punk == NULL) *phr = E_OUTOFMEMORY;
	return punk;
}
